﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NHINDirect
{
    public class Header : EntityPart
    {
        string m_name;
        string m_value;
        bool m_parsed;

        public Header(StringSegment segment)
            : base(EntityPartType.Header, segment)
        {
            this.m_parsed = false;
        }
        
        public Header(string name, string value)
            : base(EntityPartType.Header)
        {
            this.Text = Protocol.Combine(name, value);
            this.m_name = name;
            this.m_value = value;
            this.m_parsed = true;
        }
        
        public Header(KeyValuePair<string, string> value)
            : this(value.Key, value.Value)
        {        
        }
        
        /// <summary>
        /// The Text should contain a ':' separator
        /// Assumes that the text is otherwise well formed. 
        /// </summary>
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set 
            {
                base.Text = value;
                this.m_parsed = false;
            }
        }

        public string Name
        {
            get
            {
                this.EnsureNameValue();
                return this.m_name;
            }
        }

        public string Value
        {
            get
            {
                this.EnsureNameValue();
                return this.m_value;    
            }
        }
        
        internal override void AppendSourceText(StringSegment segment)
        {
            if (!this.SourceText.IsNull)
            {
                //
                // Header already has text. We need to unfold the new text in...
                //
                StringSegment unfoldedLine = EntityParser.SkipWhitespace(segment);
                if (unfoldedLine.IsEmpty)
                {
                    throw new ProtocolException(ProtocolError.InvalidHeader);
                }
                base.AppendText(unfoldedLine.ToString());
            }

            base.AppendSourceText(segment);
        }

        void EnsureNameValue()
        {
            if (this.m_parsed)
            {
                return;
            }

            string headerText = this.Text;
            int separatorPosition = EntityParser.FindChar(new StringSegment(headerText), Protocol.NameValueSeparator, true);            
            if (separatorPosition < 0)
            {
                throw new ProtocolException(ProtocolError.MissingNameValueSeparator);
            }
            if (separatorPosition == 0)
            {
                throw new ProtocolException(ProtocolError.InvalidHeader);
            }
            this.m_name = headerText.Substring(0, separatorPosition);
            separatorPosition++;
            
            if (separatorPosition == headerText.Length)
            {
                throw new ProtocolException(ProtocolError.MissingHeaderValue);
            }
            
            this.m_value = headerText.Substring(separatorPosition).TrimStart();
        }
    }
}
